/* Copyright (c) [2025] [zhi1208@126.com]
 * SPDX-License-Identifier: MIT
 */

/*********************
 *      INCLUDES
 *********************/
#include "lvgl.h"

/*********************
 *      DEFINES
 *********************/
#if (!(LV_USE_TINY_TTF && LV_TINY_TTF_FILE_SUPPORT))
#error "在lv_conf.h文件中启用宏【LV_USE_TINY_TTF】【LV_TINY_TTF_FILE_SUPPORT】"
#endif

#define HMI_ASSETS_PATH_LEN_MAX 128

#ifdef LV_PORT_VS_CODE
#define HMI_ASSETS_PATH_BASE HMI_ASSETS_DIR
#endif

#define FS_LETTER LV_FS_STDIO_LETTER

/**********************
 *      TYPEDEFS
 **********************/
typedef struct
{
    lv_font_t *font;
    const char *name;
    size_t ref_cnt;
    int32_t size;
} fixed_size_ttf_t;

/**********************
 *  STATIC PROTOTYPES
 **********************/
static fixed_size_ttf_t *locate_fixed_size_ttf_by_name(const char *path, int32_t size);
static fixed_size_ttf_t *locate_fixed_size_ttf_by_target(lv_font_t *font);
static lv_font_t *register_fixed_size_ttf(const char *name, int32_t size);

/**********************
 *  STATIC VARIABLES
 **********************/
static lv_ll_t fixed_size_ttf_list;

/**********************
 *      MACROS
 **********************/

/**********************
 *   GLOBAL FUNCTIONS
 **********************/
char *hmi_png(const char *png_name)
{
    static char asset_path[HMI_ASSETS_PATH_LEN_MAX];
    lv_snprintf(asset_path, HMI_ASSETS_PATH_LEN_MAX, "%c:" HMI_ASSETS_PATH_BASE "%s.png", FS_LETTER, png_name);
    return asset_path;
}

void hmi_tiny_ttf_font_manager_init(void)
{
    lv_ll_init(&fixed_size_ttf_list, sizeof(fixed_size_ttf_t));
}

lv_font_t *hmi_ttf_create_static(const char *static_name, int32_t size, bool var_size)
{
    LV_ASSERT_NULL(static_name);

    char path[HMI_ASSETS_PATH_LEN_MAX];
    lv_snprintf(path, HMI_ASSETS_PATH_LEN_MAX, "%c:" HMI_ASSETS_PATH_BASE "%s.ttf", FS_LETTER, static_name);

    if (!var_size)
    {
        fixed_size_ttf_t *ttf = locate_fixed_size_ttf_by_name(static_name, size);
        if (ttf)
        {
            ttf->ref_cnt++;
            return ttf->font;
        }
        else
        {
            lv_font_t *font = register_fixed_size_ttf(static_name, size);
            return font;
        }
    }
    else
    {
        lv_font_t *font = lv_tiny_ttf_create_file(path, size);
        return font;
    }
}

void hmi_ttf_del(lv_font_t *font)
{
    LV_ASSERT_NULL(font);

    fixed_size_ttf_t *ttf = locate_fixed_size_ttf_by_target(font);
    if (ttf)
    {
        if (!(--(ttf->ref_cnt)))
        {
            lv_tiny_ttf_destroy(ttf->font);
            lv_ll_remove(&fixed_size_ttf_list, ttf);
            lv_free(ttf);
        }
    }
    else
        lv_tiny_ttf_destroy(font);
}

/**********************
 *   STATIC FUNCTIONS
 **********************/
static fixed_size_ttf_t *locate_fixed_size_ttf_by_name(const char *name, int32_t size)
{
    LV_ASSERT_NULL(name);

    fixed_size_ttf_t *node = lv_ll_get_head(&fixed_size_ttf_list);
    while (node)
    {
        if (!lv_strcmp(node->name, name) && node->size == size)
            return node;
        node = lv_ll_get_next(&fixed_size_ttf_list, node);
    }

    return NULL;
}

static fixed_size_ttf_t *locate_fixed_size_ttf_by_target(lv_font_t *font)
{
    LV_ASSERT_NULL(font);

    fixed_size_ttf_t *node = lv_ll_get_head(&fixed_size_ttf_list);
    while (node)
    {
        if (font == node->font)
            return node;
        node = lv_ll_get_next(&fixed_size_ttf_list, node);
    }

    return NULL;
}

static lv_font_t *register_fixed_size_ttf(const char *name, int32_t size)
{
    LV_ASSERT_NULL(name);

    char path[HMI_ASSETS_PATH_LEN_MAX];
    lv_snprintf(path, HMI_ASSETS_PATH_LEN_MAX, "%c:" HMI_ASSETS_PATH_BASE "%s.ttf", FS_LETTER, name);

    fixed_size_ttf_t *ttf = lv_ll_ins_tail(&fixed_size_ttf_list);
    ttf->font = lv_tiny_ttf_create_file(path, size);
    ttf->size = size;
    ttf->ref_cnt = 1;
    ttf->name = name;

    return ttf->font;
}
